﻿// ===============================================================================
//  Copyright © ymind.net. All rights reserved .
//  官方网站：http://ymind.net/
//  版权所有：彦铭工作室 老陈出品
// ===============================================================================

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Reflection;
using System.Web;
using System.Web.Caching;
using System.Xml;
using Lcsoft.UrlRewriter.Errors;
using Lcsoft.UrlRewriter.Logging;
using Lcsoft.UrlRewriter.Parsers;
using Lcsoft.UrlRewriter.Transforms;
using Lcsoft.UrlRewriter.Utilities;

namespace Lcsoft.UrlRewriter.Configuration
{
	/// <summary>
	/// 表示地址重写配置信息。
	/// </summary>
	public class RewriterConfiguration
	{
		private static readonly object _syncObject = new Object();
		private static readonly string _cacheName = typeof(RewriterConfiguration).AssemblyQualifiedName;

		/// <summary>
		/// 初始化 <see cref="RewriterConfiguration"/> 类的新实例。
		/// </summary>
		internal RewriterConfiguration()
		{
			this.Logger = new NullLogger();
			this.ErrorHandlers = new Dictionary<int, IRewriteErrorHandler>();
			this.Rules = new ArrayList();
			this.XPoweredBy = MessageProvider.FormatString(Message.ProductName, Assembly.GetExecutingAssembly().GetName().Version.ToString(3));
			this.DefaultDocuments = new StringCollection();

			this.ActionParsers = new ActionParserPipeline();
			this.ActionParsers.AddParser(new IfConditionActionParser());
			this.ActionParsers.AddParser(new UnlessConditionActionParser());
			this.ActionParsers.AddParser(new AddHeaderActionParser());
			this.ActionParsers.AddParser(new SetCookieActionParser());
			this.ActionParsers.AddParser(new SetPropertyActionParser());
			this.ActionParsers.AddParser(new RewriteActionParser());
			this.ActionParsers.AddParser(new RedirectActionParser());
			this.ActionParsers.AddParser(new SetStatusActionParser());
			this.ActionParsers.AddParser(new ForbiddenActionParser());
			this.ActionParsers.AddParser(new GoneActionParser());
			this.ActionParsers.AddParser(new NoRewriteActionParser());
			this.ActionParsers.AddParser(new NotAllowedActionParser());
			this.ActionParsers.AddParser(new NotFoundActionParser());
			this.ActionParsers.AddParser(new NotImplementedActionParser());

			this.ConditionParsers = new ConditionParserPipeline();
			this.ConditionParsers.AddParser(new IPAddressConditionParser());
			this.ConditionParsers.AddParser(new HeaderMatchConditionParser());
			this.ConditionParsers.AddParser(new MethodConditionParser());
			this.ConditionParsers.AddParser(new PropertyMatchConditionParser());
			this.ConditionParsers.AddParser(new ExistsConditionParser());
			this.ConditionParsers.AddParser(new UrlMatchConditionParser());

			this.Transforms = new TransformPipeline();
			this.Transforms.AddTransform(new DecodeTransform());
			this.Transforms.AddTransform(new EncodeTransform());
			this.Transforms.AddTransform(new LowerTransform());
			this.Transforms.AddTransform(new UpperTransform());
			this.Transforms.AddTransform(new Base64Transform());
			this.Transforms.AddTransform(new Base64DecodeTransform());
		}

		/// <summary>
		/// 获取地址重写规则的集合。
		/// </summary>
		public ArrayList Rules { get; private set; }

		/// <summary>
		/// 获取动作解析引擎的实例。
		/// </summary>
		public ActionParserPipeline ActionParsers { get; private set; }

		/// <summary>
		/// 获取数据转换引擎的实例。
		/// </summary>
		public TransformPipeline Transforms { get; private set; }

		/// <summary>
		/// 获取条件分析器的集合。
		/// </summary>
		public ConditionParserPipeline ConditionParsers { get; private set; }

		/// <summary>
		/// 获取错误处理提供程序的集合。
		/// </summary>
		public Dictionary<int, IRewriteErrorHandler> ErrorHandlers { get; private set; }

		/// <summary>
		/// 获取日志记录提供程序的实例。
		/// </summary>
		public IRewriteLogger Logger { get; set; }

		/// <summary>
		/// 获取默认文档的集合。
		/// </summary>
		public StringCollection DefaultDocuments { get; private set; }

		/// <summary>
		/// 获取表示地址重写功能提供者的字符串。
		/// </summary>
		internal string XPoweredBy { get; private set; }

		/// <summary>
		/// 获取当前的 <see cref="RewriterConfiguration"/> 对象。
		/// </summary>
		public static RewriterConfiguration Current
		{
			get
			{
				if (HttpModule.ConfigurationProvider == null)
				{
					var configuration = HttpRuntime.Cache.Get(_cacheName) as RewriterConfiguration;

					if (configuration == null)
					{
						lock (_syncObject)
						{
							configuration = HttpRuntime.Cache.Get(_cacheName) as RewriterConfiguration ?? Load();
						}
					}

					return configuration;
				}

				lock (_syncObject)
				{
					return HttpModule.ConfigurationProvider.Load();
				}
			}
		}

		/// <summary>
		/// 创建 <see cref="RewriterConfiguration"/> 对象的实例。
		/// </summary>
		/// <returns><see cref="RewriterConfiguration"/> 对象。</returns>
		public static RewriterConfiguration Create() { return new RewriterConfiguration(); }

		/// <summary>
		/// 加载 <see cref="RewriterConfiguration"/> 对象。
		/// </summary>
		/// <returns><see cref="RewriterConfiguration"/> 对象。</returns>
		public static RewriterConfiguration Load()
		{
			var section = ConfigurationManager.GetSection(Constants.RewriterNode) as XmlNode;

			if (section == null) return null;

			RewriterConfiguration config = null;

			if (section.Attributes != null)
			{
				var filenameNode = section.Attributes.GetNamedItem(Constants.AttrFile);

				if (filenameNode != null)
				{
					var filename = HttpContext.Current.Server.MapPath(filenameNode.Value);
					config = LoadFromFile(filename);

					if (config != null)
					{
						var fileDependency = new CacheDependency(filename);

						HttpRuntime.Cache.Add(_cacheName, config, fileDependency, DateTime.Now.AddHours(1.0), TimeSpan.Zero, CacheItemPriority.Default, null);
					}
				}
			}

			if (config == null)
			{
				config = LoadFromNode(section);

				HttpRuntime.Cache.Add(_cacheName, config, null, DateTime.Now.AddHours(1.0), TimeSpan.Zero, CacheItemPriority.Default, null);
			}

			return config;
		}

		/// <summary>
		/// 从指定文件加载 <see cref="RewriterConfiguration"/> 对象。
		/// </summary>
		/// <param name="filename">包含地址重写配置信息的文件的完整路径。</param>
		/// <returns><see cref="RewriterConfiguration"/> 对象。</returns>
		public static RewriterConfiguration LoadFromFile(string filename)
		{
			if (File.Exists(filename))
			{
				var document = new XmlDocument();

				document.Load(filename);

				return LoadFromNode(document.DocumentElement);
			}

			return null;
		}

		/// <summary>
		/// 从指定的 <see cref="XmlNode"/> 加载 <see cref="RewriterConfiguration"/> 对象。
		/// </summary>
		/// <param name="node">包含地址重写配置信息的 <see cref="XmlNode"/>。</param>
		/// <returns><see cref="RewriterConfiguration"/> 对象。</returns>
		public static RewriterConfiguration LoadFromNode(XmlNode node) { return RewriterConfigurationReader.Read(node); }
	}
}
